﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using gts;
using System.Diagnostics;
using System.Reflection;
using Communicate;
using System.Collections.Concurrent;
using CommonTools;
using BaseDll;
namespace MotionIoLib
{
    public enum AxisState
    {
        Homeing = -2,
        Moving = -1,
        NormalStop = 0,
        ServoOff = 1,
        DriveAlarm = 2,
        LimtPStop = 4,
        LimtNStop = 5,
        ErrAlarm = 6,
    }
    public struct THomePrm
    {
        public bool _bHomeDir;
        public double _iSeachOffstPluse;
        public bool _bHomeDown;//true 上升沿触发，false 下降沿触发
        public double VelH;
        public double AccH;
        public double DccH;
        public double VelL;
        public double AccL;
        public double DccL;
        public int _nHomeMode;

    }
    public enum SpeedType
    {
        High,
        Low,

    }
    public enum MoveType
    {
        Home_P,
        Home_N,
        PTP_P,
        PTP_N,
        BUF_P,
        BUF_N,
        JOG_P,
        JOG_N,
        Line2AxisAbs,
    }
    public enum GpState
    {
        GpDisable,//群组没有使能
        GpReady,//群组准备完成
        GpStoping,//群组停止
        GpErrStop,//群组错误停止
        GpMotion,//群组运行中
        Gp_AX_Motion,//群组不支持
        GpBuff,//群组缓存运动中
        GpPause,//群组暂停

    }
    public struct TMovePrm
    {
        public double VelH;
        public double AccH;
        public double DccH;
        public double VelL;
        public double AccL;
        public double DccL;
        public double PlusePerRote;
        public double AxisLeadRange;
        public double d_SommothTime;
    }
    /// <summary>
    /// 电机类型，如要添加新类型  伺服添加到SEVER 上面，步进 是在STEP
    /// </summary>
    public enum MotorType
    {
        SEVER,
        STEP,
    }


    public struct AxisIOState
    {
        public bool _bSeverOn;
        public bool _bAlarm;
        public bool _bLimtP;
        public bool _bLimtN;
        public bool _bOrg;
        public bool _bEmg;
    };
    public struct AxisPos
    {
        public double _lCmdPos;
        public double _lActPos;
        public string _strErr;
    };
    public enum BufMotionType
    {
        buf_IO,
        buf_Delay,
        buf_end,
        buf_Line2dAbs,
        buf_Line3dAbs,
        buf_Arc2dAbsCCW,
        buf_Arc2dAbsCW,
        buf_Arc2dAbsAngleCCW,
        buf_Arc2dAbsAngleCW,
    };
    public struct BufMotionParam
    {
        public BufMotionType _Type;
        public int _mode;//模式
        public int _nAxisNum;//轴个数
        public double _VelHigh;
        public double _VelLow;
        public double[] _point1;
        public double[] _point2;

        public string _strIoName;//Io名称
        public int _nCardNo;//Io所在卡号
        public int _nIoNo;//Io索引
        public int _nAxisNo;//Io轴号
        public bool _IoVal;//Io状态
        public int _nDelayMs;//毫秒延时
        public int _Circle;//圈数
    };
    public enum AxisHomeFinishFlag
    {
        NoHome = -1,
        Homeing = 0,
        Homed = 1,

    }


    public abstract class MotionCardBase
    {
        protected double[] m_nAccs;
        protected double[] m_nDecs;
        protected uint[] m_nSmoothTimes;
        protected THomePrm[] m_HomePrm;
        protected TMovePrm[] m_MovePrm;
        protected MotorType[] m_MotorType;
        protected string[] m_strAxisName;
        protected ManualResetEvent[] m_ManualEventHomeingStop;
        protected AxisState[] m_AxisStates;
        protected int m_nMinAxisNo;
        protected int m_nMaxAxisNo;
        protected ulong m_nCardIndex;
        protected AxisHomeFinishFlag[] m_nHomeFinishFlag;
        protected string m_strCardName = "";

        public void ReasetHomeFinishFlag(int nAxisNo)
        {
            m_nHomeFinishFlag[nAxisNo] = AxisHomeFinishFlag.NoHome;
        }
        public void SetHomeingFlag(int nAxisNo)
        {
            m_nHomeFinishFlag[nAxisNo] = AxisHomeFinishFlag.Homeing;
        }
        public void SetHomeFinishFlag(int nAxisNo)
        {
            m_nHomeFinishFlag[nAxisNo] = AxisHomeFinishFlag.Homed;
        }
        public AxisHomeFinishFlag GetHomeFinishFlag(int nAxisNo)
        {
            return (AxisHomeFinishFlag)Enum.Parse(typeof(AxisHomeFinishFlag), m_nHomeFinishFlag[nAxisNo].ToString());

        }
        public MotionCardBase(ulong indexCard, string strName, int nMinAxisNo, int nMaxAxisNo)
        {
            m_nCardIndex = indexCard;   //卡的标号
            m_strCardName = strName;    //卡的名字
            m_nMinAxisNo = nMinAxisNo;  //最小轴号
            m_nMaxAxisNo = nMaxAxisNo;  //最大轴号
            m_nAccs = new double[nMaxAxisNo - nMinAxisNo + 1];  //加速度
            m_nDecs = new double[nMaxAxisNo - nMinAxisNo + 1];  //减速度
            m_nSmoothTimes = new uint[nMaxAxisNo - nMinAxisNo + 1]; //平滑时间
            m_HomePrm = new THomePrm[nMaxAxisNo - nMinAxisNo + 1];  //原点参数
            m_MovePrm = new TMovePrm[nMaxAxisNo - nMinAxisNo + 1];  //移动参数
            m_nHomeFinishFlag = new AxisHomeFinishFlag[nMaxAxisNo - nMinAxisNo + 1]; //回归原点结束标志
            m_MotorType = new MotorType[nMaxAxisNo - nMinAxisNo + 1]; //电机类型 --步进 --伺服  --机械手
            m_strAxisName = new string[nMaxAxisNo - nMinAxisNo + 1];   //轴名字
            m_ManualEventHomeingStop = new ManualResetEvent[nMaxAxisNo - nMinAxisNo + 1];
            m_AxisStates = new AxisState[nMaxAxisNo - nMinAxisNo + 1];
            for (int i = 0; i < nMaxAxisNo - nMinAxisNo + 1; i++)
            {
                m_nHomeFinishFlag[i] = AxisHomeFinishFlag.NoHome;
                m_nAccs[i] = 10;
                m_nDecs[i] = 10;
                m_nSmoothTimes[i] = 20;
                m_HomePrm[i]._bHomeDir = true;
                m_HomePrm[i]._bHomeDown = false;
                m_HomePrm[i].VelH = 0;
                m_HomePrm[i].AccH = 0;
                m_HomePrm[i].DccH = 0;
                m_HomePrm[i].VelL = 0;
                m_HomePrm[i].AccL = 0;
                m_HomePrm[i].DccL = 0;
                m_HomePrm[i]._iSeachOffstPluse = 1000;
                m_HomePrm[i]._nHomeMode = 0;
                m_strAxisName[i] = i.ToString();
                m_MovePrm[i].VelH = 0;
                m_MovePrm[i].AccH = 0;
                m_MovePrm[i].DccH = 0;

                m_MovePrm[i].VelL = 0;
                m_MovePrm[i].AccL = 0;
                m_MovePrm[i].DccL = 0;
                m_MovePrm[i].PlusePerRote = 10000;
                m_MovePrm[i].AxisLeadRange = 10;

                m_MovePrm[i].d_SommothTime = 0.1;
                if (1 == i)
                {
                    m_HomePrm[i]._bHomeDir = false;
                }
                if (0 == i)
                {
                    m_HomePrm[i]._bHomeDir = false;
                }
                m_MotorType[i] = MotorType.SEVER;
                m_ManualEventHomeingStop[i] = new ManualResetEvent(false);
                m_AxisStates[i] = AxisState.NormalStop;
            }

        }

        public double GetAxisPulsesPerMM(int nAxisNo)
        {
            return (m_MovePrm[nAxisNo].PlusePerRote / m_MovePrm[nAxisNo].AxisLeadRange);
        }
        public double GetAxisSpeed(int nAxisNo, double type)
        {
            if (type == 0)
            {
                return m_MovePrm[nAxisNo].VelH;
            }
            else if (type == 1)
            {
                return m_MovePrm[nAxisNo].VelL;
            }
            else
            {
                return type;
            }
        }

        public int GetMinAxisNo() { return m_nMinAxisNo; }
        public int GetMaxAxisNo() { return m_nMaxAxisNo; }
        //public abstract int GetAxisNo(int IndexAxis)
        public int GetAxisNo(int IndexAxis)
        {
            return AxisInRang(IndexAxis) ? (IndexAxis - GetMinAxisNo()) : int.MaxValue;
        }
        public bool AxisInRang(int nAxisNo)
        {
            return nAxisNo >= m_nMinAxisNo && nAxisNo <= m_nMaxAxisNo;
        }
        public abstract bool Open();
        protected bool m_bOpen = false;
        public abstract bool IsOpen();
        public abstract bool Close();

        public abstract bool ServoOn(short nAxisNo);
        public abstract bool ServoOff(short nAxisNo);


        public abstract bool AbsMove(int nAxisNo, double nPos, double nSpeed);// 0 高速 1 中速 2 低速
        public abstract bool RelativeMove(int nAxisNo, double nPos, double nSpeed);
        //mm 转 脉冲
        public abstract bool TranMMToPluse(int nAxisNo, ref double dSpeed, ref double acc, ref double dec);

        public abstract bool TransMMToPluseForHomeParam(int nAxisNo, ref double dVelH, ref double dVelL, ref double dAccH, ref double dAccL, ref double dDecH, ref double dDecL);
        public abstract bool JogMove(int nAxisNo, bool bPositive, int bStart, double nSpeed);
        public abstract bool StopAxis(int nAxisNo);

        public abstract bool StopEmg(int nAxisNo);
        public abstract bool ReasetAxis(int nAxisNo);

        public abstract long GetMotionIoState(int nAxisNo);
        public abstract bool GetServoState(int nAxisNo);
        public abstract AxisState IsAxisNormalStop(int nAxisNo);
        public abstract bool Home(int nAxisNo, int nParam);
        public abstract bool SetActutalPos(int nAxisNo, double pos);

        public abstract bool SetCmdPos(int nAxisNo, double Pos);
        public abstract AxisState IsHomeNormalStop(int nAxisNo);
        public abstract int GetAxisPos(int nAxisNo);
        public abstract int GetAxisActPos(int nAxisNo);
        public abstract int GetAxisCmdPos(int nAxisNo);
        public abstract bool isOrgTrig(int nAxisNo);

        public abstract bool IsInpos(int nAxisNo);

        public void SetAxisMovePrm(int nAxisNo, TMovePrm prm)
        {
            if (nAxisNo >= m_MovePrm.Length || nAxisNo < 0)
                return;
            m_MovePrm[nAxisNo] = prm;
        }


        public TMovePrm GetAxisMovePrm(int nAxisNo)
        {
            return m_MovePrm[nAxisNo];
        }
        public void SetAxisHomePrm(int nAxisNo, THomePrm homePrm)
        {
            if (nAxisNo >= m_HomePrm.Length || nAxisNo < 0)
                return;
            m_HomePrm[nAxisNo] = homePrm;
        }

        public THomePrm GetHomePrm(int nAxisNo)
        {
            return m_HomePrm[nAxisNo];
        }
        public string GetAxisName(int nAxisNo)
        {
            return m_strAxisName[nAxisNo];
        }
        public void SetAxisName(int nAxisNo, string strName)
        {
            if (nAxisNo >= m_strAxisName.Length || nAxisNo < 0)
                return;
            m_strAxisName[nAxisNo] = strName;
        }
        public int FindAxisNoByName(string strName)
        {
            for (int i = 0; i < m_strAxisName.Length; i++)
            {
                if (m_strAxisName[i] == strName)
                    return GetMinAxisNo() + i;
            }

            return -1;
        }
        public MotorType GetMotorType(int nAxisNo)
        {
            return m_MotorType[nAxisNo];
        }
        public void SetMotorType(int nAxisNo, MotorType motorType)
        {
            if (nAxisNo >= m_MotorType.Length || nAxisNo < 0)
                return;
            m_MotorType[nAxisNo] = motorType;
        }
        public bool IsSever(int nAxisNo)
        {
            if (nAxisNo >= m_MotorType.Length || nAxisNo < 0)
                return false;
            return m_MotorType[nAxisNo] <= MotorType.SEVER;
        }

        public abstract bool AddAxisToGroup(int[] nAxisarr, ref object groupId);
        public virtual bool CloseAxisGroup(int[] nAxisArr, ref object group)
        {
            return true;
        }
        public virtual GpState GetGpState(object group)
        {
            return GpState.GpDisable;
        }
        public virtual int GetGpLeftSpace(object group)
        {
            return 4096;
        }
        public virtual int GpRunAlready(object group)
        {
            return 0;
        }
        public virtual bool StopGp(object group)
        {
            return true;
        }
        public virtual bool Line2Axisabs(IntPtr group, int xAxis, int yAxis, double xpos, double ypos, double acc, double dec, double velrun, double velori = 0)
        {

            return true;
        }

        public virtual bool ResetGpErr(object group)
        {
            return true;
        }
        public abstract bool AddBufMove(object objGroup, BufMotionType type, int n_Mode, ushort[] AxisList, double velHigh, double velLow, double[] Point1, double[] Point2, int Circle, ref string strError);

        public abstract bool AddBufIo(object objGroup, string strIoName, bool bVal, ref string strError);

        public abstract bool AddBufDelay(object objGroup, int nTime, ref string strError);
        public abstract bool ClearBufMove(object objGroup);

        public abstract bool StartBufMove(object objGroup);
        public virtual bool SetBufMoveParam(object objGroup, ushort[] AxisList, double velhigh, double vellow, double acc, double dec, ref string strError)
        {
            return true;
        }
        public virtual bool ReadSDOData(int nAxis, short nSlave, ushort Index, byte nSubIndex = 0, uint nUnitNum = 16)
        {
            return true;
        }
        public virtual bool WriteSDOData(int nAxis, short nSlave, int val, ushort Index, byte nSubIndex = 0, uint nUnitNum = 16)
        {
            return true;
        }
        public virtual string GetAxisErrorString(int nAxis)
        {
            return "";
        }
    }


    public struct MoveGroup
    {
        public dynamic _pGroup;//群组的索引或引用
        public int[] _nAxisArr;//群组的轴号（非系统号）
        public int[] _nSysAxisArr;//群组的轴号（系统号）
        public double _VelHighGp;//群组的高速
        public double _VelLowGp;//群组的低速
        public double _AccGp;//群组的加速度
        public double _DecGp;//群组的减速度
        public MotionCardBase _pCard; //群组所在卡的引用
        public List<BufMotionParam> _listBufMotionParams;//buf运动的集合
    }
    public class MotionMgr
    {

        private MotionMgr()
        {
        }
        ~MotionMgr()
        {
            m_bExit = true;
        }
        private static MotionMgr _MotionObj = null;
        private static object _lock = new object();
        public static MotionMgr GetInstace()
        {

            if (_MotionObj == null)
            {
                lock (_lock)
                {
                    if (_MotionObj == null)
                    {
                        _MotionObj = new MotionMgr();
                        return _MotionObj;
                    }
                    else
                        return _MotionObj;
                }
            }
            else
                return _MotionObj;
        }
        protected double RunRadio = 0.1;
        public double d_Radio
        {
            set
            {
                if (value < 0.1)
                    RunRadio = 0.1;
                else if (value > 1)
                    RunRadio = 1;
                else
                    RunRadio = value;
            }
            get
            {
                return RunRadio;
            }
        }

        public bool IsSafeFunRegister(IsSafeWhenAxisMoveHandler isSafeWhenAxisMoveHandler)
        {
            if (MotionMgr.GetInstace().m_eventIsSafeWhenAxisMove != null)
            {
                Delegate[] delegates = MotionMgr.GetInstace().m_eventIsSafeWhenAxisMove.GetInvocationList();
                if (delegates != null && delegates.Length > 0)
                {
                    for (int i = 0; i < delegates.Length; i++)
                    {
                        if (delegates[i] == isSafeWhenAxisMoveHandler.GetInvocationList()[0])
                            return true;
                    }
                }
            }
            return false;
        }


        public List<MotionCardBase> GetCardList()
        {
            return m_lisCard;
        }
        private List<MotionCardBase> m_lisCard = new List<MotionCardBase>();
        public void AddCard(string strName, ulong nCardNo, int nAxisMin, int nAxisMax)
        {
            // m_lisCard.Add(card);
            Assembly assembly = Assembly.GetAssembly(typeof(MotionCardBase));
            string name = "MotionIoLib.Motion_" + strName;
            //Motion_Advantech
            Type type = assembly.GetType(name);
            bool flag = type == null;
            if (flag)
            {
                throw new Exception(string.Format($"卡类型：{strName} 卡号：{nCardNo}+运动控制卡{0}找不到可用的封装类，请确认motionio.dll是否正确或配置错误?"));
            }
            object[] args = new object[]
            {
              nCardNo,
              strName,
              nAxisMin,
              nAxisMax
            };
            this.m_lisCard.Add(Activator.CreateInstance(type, args) as MotionCardBase);
        }
        public bool OpenAllCard()
        {
            bool bOpenFlag = true;
            foreach (var temp in m_lisCard)
            {
                // bOpenFlag=temp.Value.Close();
                bOpenFlag = bOpenFlag & temp.Open();
            }
            Thread thread = new Thread(ThreadMonitor);
            thread.IsBackground = true;
            thread.Start();
            return bOpenFlag;
        }
        public void SetAxisHomeParam(int nAxisNo, THomePrm prm)
        {
            MotionCardBase tempCardBase = GetCardByIndexAxis(nAxisNo);
            int nAxis = 0;
            if (tempCardBase != null)
            {
                nAxis = tempCardBase.GetAxisNo(nAxisNo);
                tempCardBase.SetAxisHomePrm(nAxis, prm);
            }
        }
        public THomePrm GetAxisHomePrm(int nAxisNo)
        {
            THomePrm prm = new THomePrm();
            MotionCardBase tempCardBase = GetCardByIndexAxis(nAxisNo);
            int nAxis = 0;
            if (tempCardBase != null)
            {
                nAxis = tempCardBase.GetAxisNo(nAxisNo);
                return tempCardBase.GetHomePrm(nAxis);
            }
            else
                return prm;
        }
        public void SetAxisMoveParam(int nAxisNo, TMovePrm prm)
        {
            MotionCardBase tempCardBase = GetCardByIndexAxis(nAxisNo);
            int nAxis = 0;
            if (tempCardBase != null)
            {
                nAxis = tempCardBase.GetAxisNo(nAxisNo);
                tempCardBase.SetAxisMovePrm(nAxis, prm);
            }
        }
        public TMovePrm GetAxisMovePrm(int nAxisNo)
        {
            TMovePrm prm = new TMovePrm();
            MotionCardBase tempCardBase = GetCardByIndexAxis(nAxisNo);
            int nAxis = 0;
            if (tempCardBase != null)
            {
                nAxis = tempCardBase.GetAxisNo(nAxisNo);
                return tempCardBase.GetAxisMovePrm(nAxis);
            }
            else
                return prm;
        }
        public void SetMotorType(int nAxisNo, MotorType motorType)
        {

            MotionCardBase tempCardBase = GetCardByIndexAxis(nAxisNo);
            int nAxis = 0;
            if (tempCardBase != null)
            {
                nAxis = tempCardBase.GetAxisNo(nAxisNo);
                tempCardBase.SetMotorType(nAxis, motorType);
            }

        }
        public MotorType GetMotorType(int nAxisNo)
        {
            MotorType motorType = new MotorType();
            MotionCardBase tempCardBase = GetCardByIndexAxis(nAxisNo);
            int nAxis = 0;
            if (tempCardBase != null)
            {
                nAxis = tempCardBase.GetAxisNo(nAxisNo);
                return tempCardBase.GetMotorType(nAxis);
            }
            else
                return motorType;
        }
        public void SetAxisHomeFinishFlag(int nAxisNo)
        {
            MotionCardBase tempCardBase = GetCardByIndexAxis(nAxisNo);
            int nAxis = 0;
            if (tempCardBase != null)
            {
                nAxis = tempCardBase.GetAxisNo(nAxisNo);
                tempCardBase.SetHomeFinishFlag(nAxis);

            }
        }
        public void SetAxisHomeingFlag(int nAxisNo)
        {
            MotionCardBase tempCardBase = GetCardByIndexAxis(nAxisNo);
            int nAxis = 0;
            if (tempCardBase != null)
            {
                nAxis = tempCardBase.GetAxisNo(nAxisNo);
                tempCardBase.SetHomeingFlag(nAxis);

            }
        }

        public void ReasetAxisHomeFinishFlag(int nAxisNo)
        {
            MotionCardBase tempCardBase = GetCardByIndexAxis(nAxisNo);
            int nAxis = 0;
            if (tempCardBase != null)
            {
                nAxis = tempCardBase.GetAxisNo(nAxisNo);
                tempCardBase.ReasetHomeFinishFlag(nAxis);

            }
        }
        public AxisHomeFinishFlag GetHomeFinishFlag(int nAxisNo)
        {
            MotionCardBase tempCardBase = GetCardByIndexAxis(nAxisNo);
            int nAxis = 0;
            if (tempCardBase != null)
            {
                nAxis = tempCardBase.GetAxisNo(nAxisNo);
                AxisHomeFinishFlag axisHomeFinishFlag = tempCardBase.GetHomeFinishFlag(nAxis);
                return axisHomeFinishFlag;
            }
            else
                return AxisHomeFinishFlag.NoHome;
        }

        public string GetAxisName(int nAxisNo)
        {
            string strAxisName = "";
            MotionCardBase tempCardBase = GetCardByIndexAxis(nAxisNo);
            int nAxis = 0;
            if (tempCardBase != null)
            {
                nAxis = tempCardBase.GetAxisNo(nAxisNo);
                return tempCardBase.GetAxisName(nAxis);
            }
            else
                return strAxisName;
        }
        public void SetAxisName(int nAxisNo, string strName)
        {

            MotionCardBase tempCardBase = GetCardByIndexAxis(nAxisNo);
            int nAxis = 0;
            if (tempCardBase != null)
            {
                nAxis = tempCardBase.GetAxisNo(nAxisNo);
                tempCardBase.SetAxisName(nAxis, strName);
            }
        }

        public bool Close()
        {
            bool bCloseFlag = true;
            foreach (var temp in m_lisCard)
            {
                bCloseFlag = bCloseFlag & temp.Close();
            }
            return bCloseFlag;
        }
        public MotionCardBase GetCardByIndexAxis(int nAxisNo)
        {
            MotionCardBase tempCardBase = null;
            foreach (var temp in m_lisCard)
            {
                if (temp.AxisInRang(nAxisNo))
                    tempCardBase = temp;
            }
            return tempCardBase;
        }
        public int GetAxisNoByName(string strAxisName)
        {
            int nAxisNo = 0;
            foreach (var temp in m_lisCard)
            {
                nAxisNo = temp.FindAxisNoByName(strAxisName);
                if (nAxisNo != -1)
                    return nAxisNo;

            }
            return -1;
        }
        public bool ServoOn(short nAxisNo)
        {

            MotionCardBase tempCardBase = GetCardByIndexAxis(nAxisNo);
            int nAxis = 0;
            if (tempCardBase != null)
            {
                nAxis = tempCardBase.GetAxisNo(nAxisNo);
                //if (tempCardBase.IsSever(nAxis))
                //    return tempCardBase.ServoOn((short)nAxis);
                //else
                //    return false;
                return tempCardBase.ServoOn((short)nAxis);
            }
            else
                return false;
        }
        public bool ServoOff(short nAxisNo)
        {
            MotionCardBase tempCardBase = GetCardByIndexAxis(nAxisNo);
            int nAxis = 0;
            if (tempCardBase != null)
            {
                nAxis = tempCardBase.GetAxisNo(nAxisNo);
                //if (tempCardBase.IsSever(nAxis))
                //    return tempCardBase.ServoOff((short)nAxis);
                //else
                //    return false;
                return tempCardBase.ServoOff((short)nAxis);
            }
            else
                return false;
        }
        public bool AbsMove(int nAxisNo, double nPos, double nSpeed, ref string strError)
        {
            MotionCardBase cardByIndexAxis = GetCardByIndexAxis(nAxisNo);
            int num = 0;
            if (cardByIndexAxis != null)
            {
                string axisName = GetAxisName(nAxisNo);
                double num2 = 9.2233720368547758E+18;
                num2 = GetAxisActPos(nAxisNo);
                bool flag = true;
                if (this.m_eventIsSafeWhenAxisMove != null)
                {
                    Delegate[] invocationList = this.m_eventIsSafeWhenAxisMove.GetInvocationList();
                    Delegate[] array = invocationList;
                    foreach (Delegate del in array)
                    {
                        MethodInfo methodInfo = del.GetMethodInfo();
                        flag &= (bool)methodInfo.Invoke(null, new object[4]
                        {
                        nAxisNo,
                        num2,
                        nPos,
                        (nPos > num2) ? MoveType.PTP_P : MoveType.PTP_N
                        });
                    }
                }

                if (!flag)
                {
                    strError = $"{axisName}轴AbsMove 运动到{nPos}开始 安全检查失败";
                    DeviceDataCollect.GetInstance().Function_MachineLog(axisName, strError);
                    return false;
                }

                DeviceDataCollect.GetInstance().Function_MachineLog(axisName, $"{axisName}轴AbsMove 运动到{nPos}");
                num = cardByIndexAxis.GetAxisNo(nAxisNo);
                double axisPulsesPerMM = cardByIndexAxis.GetAxisPulsesPerMM(num);
                if (cardByIndexAxis.AbsMove(num, nPos * axisPulsesPerMM, nSpeed))
                {
                    return true;
                }

                strError = cardByIndexAxis.GetAxisErrorString(num);
                return false;
            }

            strError = $"轴号{num}不在轴配置中";
            return false;

            //MotionCardBase tempCardBase = GetCardByIndexAxis(nAxisNo);
            //int nAxis = 0;
            //if (tempCardBase != null)
            //{
            //    string strAxisName = GetAxisName(nAxisNo);
            //    double currentpos = long.MaxValue;
            //    double destpos = nPos;
            //    currentpos = GetAxisActPos(nAxisNo);

            //    //轴运动安全检查
            //    bool bSave = true;
            //    if (m_eventIsSafeWhenAxisMove != null)
            //    {
            //        Delegate[] delegates = m_eventIsSafeWhenAxisMove.GetInvocationList();
            //        foreach (var tem in delegates)
            //        {
            //            MethodInfo methodInfo = tem.GetMethodInfo();
            //            bSave = bSave & (bool)methodInfo.Invoke(null, new object[] { nAxisNo, currentpos, destpos, destpos > currentpos ? MoveType.PTP_P : MoveType.PTP_N });
            //        }
            //    }
            //    if (!bSave)
            //    {
            //        strError = string.Format("{0}轴AbsMove 运动到{1}开始 安全检查失败", strAxisName, destpos);
            //        DeviceDataCollect.GetInstance().Function_MachineLog(strAxisName, strError);
            //        return false;
            //    }
            //    DeviceDataCollect.GetInstance().Function_MachineLog(strAxisName, $"{strAxisName}轴AbsMove 运动到{destpos}");
            //    nAxis = tempCardBase.GetAxisNo(nAxisNo);
            //    double rate = tempCardBase.GetAxisPulsesPerMM(nAxis);
            //    if (tempCardBase.AbsMove(nAxis, nPos * rate, nSpeed))
            //        return true;
            //    else
            //    {
            //        strError = tempCardBase.GetAxisErrorString(nAxis);
            //        return false;
            //    }
            //}
            //else
            //{
            //    strError = $"轴号{nAxis}不在轴配置中";
            //    return false;
            //}
        }
        public double GetAxisPulsesPerMM(int nAxisNo)
        {
            MotionCardBase tempCardBase = GetCardByIndexAxis(nAxisNo);
            int nAxis = tempCardBase.GetAxisNo(nAxisNo);
            double rate = tempCardBase.GetAxisPulsesPerMM(nAxis);
            return rate;

        }
        public double GetAxisSpeed(int nAxisNo, double tpye)
        {
            MotionCardBase tempCardBase = GetCardByIndexAxis(nAxisNo);
            int nAxis = tempCardBase.GetAxisNo(nAxisNo);
            double rate = tempCardBase.GetAxisSpeed(nAxis, tpye);
            return rate;

        }
        public bool RelativeMove(int nAxisNo, double nPos, double nSpeed, ref string strError)
        {

            MotionCardBase tempCardBase = GetCardByIndexAxis(nAxisNo);
            int nAxis = 0;
            if (tempCardBase != null)
            {
                string strAxisName = GetAxisName(nAxisNo);
                double currentpos = long.MaxValue;
                double destpos = nPos;
                currentpos = GetAxisActPos(nAxisNo);
                destpos = nPos + currentpos;
                //轴运动安全检查
                bool bSave = true;
                if (m_eventIsSafeWhenAxisMove != null)
                {
                    Delegate[] delegates = m_eventIsSafeWhenAxisMove.GetInvocationList();
                    foreach (var tem in delegates)
                    {
                        MethodInfo methodInfo = tem.GetMethodInfo();
                        bSave = bSave & (bool)methodInfo.Invoke(null, new object[] { nAxisNo, currentpos, destpos, destpos > currentpos ? MoveType.PTP_P : MoveType.PTP_N });
                    }
                }
                if (!bSave)
                {
                    strError = string.Format("{0}轴RelativeMove 运动到{1}开始 安全检查失败", strAxisName, destpos);
                    DeviceDataCollect.GetInstance().Function_MachineLog(strAxisName, strError);
                    return false;
                }
                DeviceDataCollect.GetInstance().Function_MachineLog(strAxisName, $"{strAxisName}轴RelativeMove 运动到{destpos}");
                nAxis = tempCardBase.GetAxisNo(nAxisNo);
                double rate = tempCardBase.GetAxisPulsesPerMM(nAxis);
                if (tempCardBase.RelativeMove(nAxis, nPos * rate, nSpeed))
                    return true;
                else
                {
                    strError = tempCardBase.GetAxisErrorString(nAxis);
                    return false;
                }

            }
            else
            {
                strError = $"轴号{nAxis}不在轴配置中";
                return false;
            }

        }
        public bool JogMove(int nAxisNo, bool bPositive, int bStart, double nSpeed, ref string strError)
        {

            MotionCardBase tempCardBase = GetCardByIndexAxis(nAxisNo);
            int nAxis = 0;
            if (tempCardBase != null)
            {
                string strAxisName = GetAxisName(nAxisNo);
                double currentpos = long.MaxValue;
                double destpos = long.MaxValue;
                currentpos = GetAxisActPos(nAxisNo);
                if (bPositive)
                    destpos = currentpos + 100;
                else
                    destpos = currentpos - 100;
                //轴运动安全检查
                bool bSave = true;
                if (m_eventIsSafeWhenAxisMove != null)
                {
                    Delegate[] delegates = m_eventIsSafeWhenAxisMove.GetInvocationList();
                    foreach (var tem in delegates)
                    {
                        MethodInfo methodInfo = tem.GetMethodInfo();
                        bSave = bSave & (bool)methodInfo.Invoke(null, new object[] { nAxisNo, currentpos, destpos, bPositive ? MoveType.JOG_P : MoveType.JOG_N });
                    }
                }
                if (!bSave)
                {
                    strError = string.Format("{0}轴JogMove 运动到{1}开始 安全检查失败", strAxisName, destpos);
                    DeviceDataCollect.GetInstance().Function_MachineLog(strAxisName, strError);
                    return false;
                }
                DeviceDataCollect.GetInstance().Function_MachineLog(strAxisName, $"{strAxisName}轴启动Jog运动，方向：{bPositive}");
                nAxis = tempCardBase.GetAxisNo(nAxisNo);
                if (tempCardBase.JogMove(nAxis, bPositive, bStart, nSpeed))
                    return true;
                else
                {
                    strError = tempCardBase.GetAxisErrorString(nAxis);
                    return false;
                }

            }
            else
            {
                strError = $"轴号{nAxis}不在轴配置中";
                return false;
            }
        }
        public bool StopAxis(int nAxisNo)
        {
            MotionCardBase tempCardBase = GetCardByIndexAxis(nAxisNo);
            int nAxis = 0;
            if (tempCardBase != null)
            {
                string strAxisName = GetAxisName(nAxisNo);
                DeviceDataCollect.GetInstance().Function_MachineLog(strAxisName, $"{strAxisName}轴StopAxis 运动停止");
                nAxis = tempCardBase.GetAxisNo(nAxisNo);
                return tempCardBase.StopAxis(nAxis);
            }
            else
                return false;
        }
        public long GetMotionIoState(int nAxisNo)
        {
            MotionCardBase tempCardBase = GetCardByIndexAxis(nAxisNo);
            int nAxis = 0;
            if (tempCardBase != null)
            {
                nAxis = tempCardBase.GetAxisNo(nAxisNo);
                return tempCardBase.GetMotionIoState(nAxis);
            }
            else
                return 0;
        }
        public bool GetServoState(int nAxisNo)
        {
            MotionCardBase tempCardBase = GetCardByIndexAxis(nAxisNo);
            int nAxis = 0;
            if (tempCardBase != null)
            {
                nAxis = tempCardBase.GetAxisNo(nAxisNo);
                return tempCardBase.GetServoState(nAxis);
            }
            else
                return false;
        }
        public AxisState IsAxisNormalStop(int nAxisNo)
        {
            MotionCardBase tempCardBase = GetCardByIndexAxis(nAxisNo);
            int nAxis = 0;
            if (tempCardBase != null)
            {
                nAxis = tempCardBase.GetAxisNo(nAxisNo);
                AxisState state = tempCardBase.IsAxisNormalStop(nAxis);
                if (state > AxisState.NormalStop)
                {
                    Stopwatch stopwatch = new Stopwatch();
                    stopwatch.Start();
                    while (true)
                    {
                        Thread.Sleep(1);
                        state = tempCardBase.IsAxisNormalStop(nAxis);
                        if (state > AxisState.NormalStop)
                        {
                            if (stopwatch.ElapsedMilliseconds > 1000)
                                break;
                        }
                        else
                            break;
                    }
                }
                return state;
            }
            else
                return 0;
        }
        public bool Home(int nAxisNo, int nParam, ref string strError)
        {

            MotionCardBase tempCardBase = GetCardByIndexAxis(nAxisNo);
            int nAxis = 0;
            if (tempCardBase != null)
            {
                string strAxisName = GetAxisName(nAxisNo);
                double currentpos = long.MaxValue;
                double destpos = long.MaxValue;
                currentpos = GetAxisActPos(nAxisNo);
                destpos = currentpos;
                //轴运动安全检查
                bool bSave = true;
                if (m_eventIsSafeWhenAxisMove != null)
                {
                    Delegate[] delegates = m_eventIsSafeWhenAxisMove.GetInvocationList();
                    foreach (var tem in delegates)
                    {
                        MethodInfo methodInfo = tem.GetMethodInfo();
                        bSave = bSave & (bool)methodInfo.Invoke(null, new object[] { nAxisNo, currentpos, destpos, GetAxisHomePrm(nAxisNo)._bHomeDir ? MoveType.Home_P : MoveType.Home_N });
                    }
                }
                if (!bSave)
                {
                    strError = $"{strAxisName}轴Home 安全检测失败";
                    DeviceDataCollect.GetInstance().Function_MachineLog(strAxisName, strError);
                    return false;
                }
                DeviceDataCollect.GetInstance().Function_MachineLog(strAxisName, $"{strAxisName}轴Home 开始");
                nAxis = tempCardBase.GetAxisNo(nAxisNo);
                return tempCardBase.Home(nAxis, 0);
            }
            else
                return false;
        }
        public bool isOrgTrig(int nAxisNo)
        {
            MotionCardBase tempCardBase = GetCardByIndexAxis(nAxisNo);
            int nAxis = 0;
            if (tempCardBase != null)
            {
                nAxis = tempCardBase.GetAxisNo(nAxisNo);
                bool bsignal = tempCardBase.isOrgTrig(nAxis); ;
                return bsignal;
            }
            else
                return false;
        }
        public bool IsHomeNormalStop(int nAxisNo)
        {
            MotionCardBase tempCardBase = GetCardByIndexAxis(nAxisNo);
            int nAxis = 0;
            if (tempCardBase != null)
            {
                nAxis = tempCardBase.GetAxisNo(nAxisNo);
                AxisState axisState = tempCardBase.IsHomeNormalStop(nAxis); ;
                return axisState == AxisState.NormalStop;
            }
            else
                return false;
        }

        public bool SetAxisActualPos(int nAxisNo, double pos)
        {
            if (nAxisNo == -1)
                return true;
            MotionCardBase tempCardBase = GetCardByIndexAxis(nAxisNo);
            int nAxis = 0;
            if (tempCardBase != null)
            {
                nAxis = tempCardBase.GetAxisNo(nAxisNo);
                return tempCardBase.SetActutalPos(nAxis, pos);
            }
            else
                return false;
        }

        public bool SetAxisCmdPos(int nAxisNo, double pos)
        {
            if (nAxisNo == -1)
                return true;
            MotionCardBase tempCardBase = GetCardByIndexAxis(nAxisNo);
            int nAxis = 0;
            if (tempCardBase != null)
            {
                nAxis = tempCardBase.GetAxisNo(nAxisNo);
                return tempCardBase.SetCmdPos(nAxis, pos);
            }
            else
                return false;
        }
        public double GetAxisActPos(int nAxisNo)
        {
            if (nAxisNo == -1)
                return int.MaxValue;
            MotionCardBase tempCardBase = GetCardByIndexAxis(nAxisNo);
            int nAxis = 0;
            if (tempCardBase != null)
            {
                nAxis = tempCardBase.GetAxisNo(nAxisNo);
                double rate = tempCardBase.GetAxisPulsesPerMM(nAxis);
                if (rate == 0)
                    rate = 1;
                if (GetMotorType(nAxis) == MotorType.STEP)
                    return tempCardBase.GetAxisCmdPos(nAxis) / rate;
                else
                    return tempCardBase.GetAxisActPos(nAxis) / rate;
            }
            else
                return int.MaxValue;
        }
        public double GetAxisCmdPos(int nAxisNo)
        {
            if (nAxisNo == -1)
                return int.MaxValue;
            MotionCardBase tempCardBase = GetCardByIndexAxis(nAxisNo);
            int nAxis = 0;
            if (tempCardBase != null)
            {
                nAxis = tempCardBase.GetAxisNo(nAxisNo);
                double rate = tempCardBase.GetAxisPulsesPerMM(nAxis);
                if (rate == 0)
                    rate = 1;

                return tempCardBase.GetAxisCmdPos(nAxis) / rate;
            }
            else
                return int.MaxValue;
        }
        public bool IsInPos(int nAxisNo)
        {
            MotionCardBase tempCardBase = GetCardByIndexAxis(nAxisNo);
            int nAxis = 0;
            if (tempCardBase != null)
            {
                nAxis = tempCardBase.GetAxisNo(nAxisNo);
                return tempCardBase.IsInpos(nAxis);
            }
            else
                return false;
        }
        public bool StopEmg(int nAxisNo)
        {
            MotionCardBase tempCardBase = GetCardByIndexAxis(nAxisNo);
            int nAxis = 0;
            if (tempCardBase != null)
            {
                nAxis = tempCardBase.GetAxisNo(nAxisNo);
                return tempCardBase.StopEmg(nAxis);
            }
            else
                return false;
        }
        public bool StopEmg()
        {
            int nAxis = 0;
            bool result = true;
            foreach (var temp in m_lisCard)
            {
                for (int i = temp.GetMinAxisNo(); i <= temp.GetMinAxisNo(); i++)
                {
                    nAxis = temp.GetAxisNo(i);
                    result = result & temp.StopEmg(nAxis);
                }

            }
            return result;
        }
        public bool ResetAxis()
        {
            int nAxis = 0;
            bool result = true;
            foreach (var temp in m_lisCard)
            {
                for (int i = temp.GetMinAxisNo(); i <= temp.GetMinAxisNo(); i++)
                {
                    nAxis = temp.GetAxisNo(i);
                    result = result & temp.ReasetAxis(nAxis);
                }

            }
            return result;
        }
        public bool ResetAxis(int nAxisNo)
        {
            MotionCardBase tempCardBase = GetCardByIndexAxis(nAxisNo);
            int nAxis = 0;
            if (tempCardBase != null)
            {
                nAxis = tempCardBase.GetAxisNo(nAxisNo);
                return tempCardBase.ReasetAxis(nAxis);
            }
            else
                return false;
        }

        AxisIOState[] m_arrAxisIOState = new AxisIOState[100];
        AxisPos[] m_arrAxisPos = new AxisPos[100];
        object m_lockReadAxisIO = new object();
        public delegate void ChangeMotionIoOrPosHandler(int nAxisNo, bool[] bChangeBitArr, AxisIOState state, AxisPos axisPos, string strError);
        public event ChangeMotionIoOrPosHandler m_eventChangeMotionIoOrPos;
        public delegate bool IsSafeWhenAxisMoveHandler(int nAxisNo, double currentpos, double dsstpos, MoveType moveType);
        public event IsSafeWhenAxisMoveHandler m_eventIsSafeWhenAxisMove = null;

        //轴信号处理
        public delegate void AxismSinglHandler(string IoName, bool bCurrentState);
        public event AxismSinglHandler m_eventAxisSingl = null;




        private bool m_bExit = false;
        public void ThreadMonitor()
        {
            //驱动器报警存在第1位
            //正限位报警存在第2位
            //负限位报警存在第3位
            //急停触发存在第5位
            //电机到位标志存在第7位
            //电机使能标志存在第8位
            long val;
            AxisIOState axisIOState = new AxisIOState();
            AxisPos axisPos = new AxisPos();
            bool[] bChangeBitArr = new bool[8] { false, false, false, false, false, false, false, false };
            int nMinAxisNo = 0;
            double rate = 1;
            Stopwatch stopwatch = new Stopwatch();
            stopwatch.Restart();
            while (!m_bExit)
            {

                foreach (var temp in m_lisCard)
                {
                    nMinAxisNo = temp.GetMinAxisNo();
                    for (int index = nMinAxisNo; index <= temp.GetMaxAxisNo(); index++)
                    {
                        if (!temp.IsOpen())
                        {
                            Thread.Sleep(100);
                            continue;
                        }

                        val = temp.GetMotionIoState(index - nMinAxisNo);
                        rate = temp.GetAxisPulsesPerMM(index - nMinAxisNo);
                        //   if(stopwatch.ElapsedMilliseconds%500==0)
                        //       temp.ResetAllAxis();
                        if (rate == 0)
                            rate = 1;
                        axisPos._lActPos = temp.GetAxisActPos(index - nMinAxisNo) / rate;

                        axisPos._lCmdPos = temp.GetAxisCmdPos(index - nMinAxisNo) / rate;
                        axisPos._strErr = temp.GetAxisErrorString(index - nMinAxisNo);
                        lock (m_lockReadAxisIO)
                        {
                            axisIOState._bAlarm = (val & (0x01 << 0)) > 0;
                            axisIOState._bLimtP = (val & (0x01 << 1)) > 0;
                            axisIOState._bLimtN = (val & (0x01 << 2)) > 0;
                            axisIOState._bOrg = (val & (0x01 << 3)) > 0;
                            axisIOState._bEmg = (val & (0x01 << 4)) > 0;
                            axisIOState._bSeverOn = (val & (0x01 << 7)) > 0;
                            if (m_arrAxisIOState[index]._bOrg != axisIOState._bOrg ||
                                m_arrAxisIOState[index]._bAlarm != axisIOState._bAlarm ||
                                m_arrAxisIOState[index]._bLimtN != axisIOState._bLimtN ||
                                m_arrAxisIOState[index]._bLimtP != axisIOState._bLimtP ||
                              /*  m_arrAxisIOState[index]._bEmg != */axisIOState._bEmg ||
                                m_arrAxisIOState[index]._bEmg != axisIOState._bEmg ||
                                m_arrAxisIOState[index]._bSeverOn != axisIOState._bSeverOn ||
                                axisPos._lActPos != m_arrAxisPos[index]._lActPos ||
                                axisPos._lCmdPos != m_arrAxisPos[index]._lCmdPos ||
                                axisPos._strErr != m_arrAxisPos[index]._strErr
                                )
                            {
                                if (m_arrAxisIOState[index]._bSeverOn != axisIOState._bSeverOn)
                                    bChangeBitArr[0] = true;
                                if (m_arrAxisIOState[index]._bAlarm != axisIOState._bAlarm)
                                {
                                    if (m_eventAxisSingl != null && axisIOState._bLimtP)
                                        m_eventAxisSingl("报警", axisIOState._bLimtP);
                                    bChangeBitArr[1] = true;
                                }
                                if (m_arrAxisIOState[index]._bLimtP != axisIOState._bLimtP)
                                {
                                    if (m_eventAxisSingl != null && axisIOState._bLimtP)
                                        m_eventAxisSingl("正极限", axisIOState._bLimtP);
                                    bChangeBitArr[2] = true;
                                }

                                if (m_arrAxisIOState[index]._bLimtN != axisIOState._bLimtN)
                                {
                                    if (m_eventAxisSingl != null && axisIOState._bLimtN)
                                        m_eventAxisSingl("负极限", axisIOState._bLimtN);
                                    bChangeBitArr[3] = true;
                                }
                                if (m_arrAxisIOState[index]._bOrg != axisIOState._bOrg)
                                {
                                    if (m_eventAxisSingl != null && axisIOState._bOrg)
                                        m_eventAxisSingl("原点", axisIOState._bOrg);
                                    bChangeBitArr[4] = true;

                                }
                                if (/*m_arrAxisIOState[index]._bEmg != */axisIOState._bEmg)
                                {
                                    if (m_eventAxisSingl != null && axisIOState._bEmg)
                                        m_eventAxisSingl("急停", axisIOState._bEmg);
                                    bChangeBitArr[5] = true;
                                }
                                if (m_arrAxisIOState[index]._bEmg != axisIOState._bEmg)
                                {
                                    if (m_eventAxisSingl != null && axisIOState._bEmg)
                                        m_eventAxisSingl("急停", axisIOState._bEmg);
                                    bChangeBitArr[5] = true;
                                }
                                if (axisPos._lActPos != m_arrAxisPos[index]._lActPos)
                                    bChangeBitArr[6] = true;
                                if (axisPos._lCmdPos != m_arrAxisPos[index]._lCmdPos)
                                    bChangeBitArr[7] = true;
                                if (axisPos._strErr != m_arrAxisPos[index]._strErr)
                                    m_arrAxisPos[index]._strErr = axisPos._strErr;
                                m_arrAxisIOState[index] = axisIOState;
                                m_arrAxisPos[index] = axisPos;
                                if (m_eventChangeMotionIoOrPos != null)
                                    m_eventChangeMotionIoOrPos(index, bChangeBitArr, axisIOState, axisPos, axisPos._strErr);

                            }

                        }
                    }
                    for (int i = 0; i < bChangeBitArr.Length; i++)
                        bChangeBitArr[i] = false;
                }
                Thread.Sleep(100);
            }
        }
        public bool GetAxisIOState(int nAxis, ref AxisIOState axisIOState)
        {
            if (nAxis >= m_arrAxisIOState.Length || nAxis < 0)
                return false;
            else
            {
                lock (m_lockReadAxisIO)
                {
                    axisIOState = m_arrAxisIOState[nAxis];
                }
                return true;
            }
        }
        public bool GetAxisPos(int nAxis, ref AxisPos axispos)
        {
            if (nAxis >= m_arrAxisPos.Length || nAxis < 0)
                return false;
            else
            {
                lock (m_lockReadAxisIO)
                {
                    axispos = m_arrAxisPos[nAxis];
                }
                return true;
            }
        }

        public ConcurrentDictionary<string, MoveGroup> m_dicGroup = new ConcurrentDictionary<string, MoveGroup>();
        public MoveGroup GetMoveGrop(string strGpName)
        {
            MoveGroup moveGroup = new MoveGroup();
            if (m_dicGroup.ContainsKey(strGpName))
            {
                moveGroup = m_dicGroup[strGpName];
                return moveGroup;
            }
            return moveGroup;

        }
        public void SetMoveGrop(string strGpName, MoveGroup moveGroup)
        {
            if (m_dicGroup.ContainsKey(strGpName))
            {
                m_dicGroup[strGpName] = moveGroup;
            }
        }
        /// <summary>
        /// 添加一个群组
        /// </summary>
        /// <param name="GroupName"></param>
        /// <param name="nAxisArr"></param>
        public bool AddAxisToGroup(string GroupName, int[] nAxisArr)
        {
            if (nAxisArr == null || nAxisArr.Length <= 0)
                return false;
            MoveGroup moveGroup = new MoveGroup();
            moveGroup._nAxisArr = new int[nAxisArr.Length];
            moveGroup._nSysAxisArr = new int[nAxisArr.Length];
            for (int i = 0; i < nAxisArr.Length; i++)
            {
                moveGroup._nAxisArr[i] = GetCardByIndexAxis(nAxisArr[i]).GetAxisNo(nAxisArr[i]);
                moveGroup._nSysAxisArr[i] = nAxisArr[i];
            }


            MotionCardBase tempCardBase = GetCardByIndexAxis(nAxisArr[0]);
            moveGroup._pCard = tempCardBase;
            object intPtr = 1;
            if (!m_dicGroup.ContainsKey(GroupName))
            {
                if (m_dicGroup.Count == 0)
                    intPtr = 1;
                else
                    intPtr = 2;

            }
            else
            {
                intPtr = m_dicGroup[GroupName]._pGroup;
            }
            try
            {

                if ((bool)tempCardBase?.AddAxisToGroup(moveGroup._nAxisArr, ref intPtr))
                {
                    moveGroup._pGroup = intPtr;
                    moveGroup._listBufMotionParams = new List<BufMotionParam>();
                    moveGroup._listBufMotionParams.Clear();
                    if (!m_dicGroup.ContainsKey(GroupName))
                    {
                        m_dicGroup.TryAdd(GroupName, moveGroup);
                    }
                    else
                    {
                        m_dicGroup[GroupName] = moveGroup;
                    }
                    return true;
                }
                else
                {
                    return false;
                }

            }
            catch (Exception)
            {
            }


            return false;
        }

        public void SetGpParam(string strGpName, double acc, double dec, double velrun, double velori = 0)
        {
            if (m_dicGroup.ContainsKey(strGpName))
            {
                MoveGroup moveGroup = m_dicGroup[strGpName];
                moveGroup._AccGp = acc;
                moveGroup._DecGp = dec;
                moveGroup._VelHighGp = velrun;
                moveGroup._VelLowGp = velori;
                m_dicGroup[strGpName] = moveGroup;

            }
        }

        public GpState GetGpState(string strGpName)
        {
            if (m_dicGroup.ContainsKey(strGpName))
            {
                MoveGroup moveGroup = m_dicGroup[strGpName];
                if (moveGroup._pCard == null)
                {
                    return GpState.GpDisable;
                }
                if (moveGroup._nAxisArr == null || moveGroup._nAxisArr.Length <= 1)
                {
                    return GpState.GpDisable;
                }
                if (moveGroup._pGroup == null)
                {
                    return GpState.GpDisable;
                }
                return moveGroup._pCard.GetGpState(moveGroup._pGroup);

            }
            return GpState.GpDisable;
        }
        public bool StopGp(string strGpName)
        {
            if (m_dicGroup.ContainsKey(strGpName))
            {
                MoveGroup moveGroup = m_dicGroup[strGpName];
                if (moveGroup._pCard == null)
                {
                    return false;
                }

                if (moveGroup._nAxisArr == null || moveGroup._nAxisArr.Length <= 1)
                {
                    return false;
                }
                if (moveGroup._pGroup == null)
                {
                    return false;
                }
                IntPtr intPtrgroup = (IntPtr)moveGroup._pGroup;
                return moveGroup._pCard.StopGp(intPtrgroup);

            }
            return false;
        }
        public int GetGpLeftSpace(string strGpName)
        {
            if (m_dicGroup.ContainsKey(strGpName))
            {
                MoveGroup moveGroup = m_dicGroup[strGpName];
                if (moveGroup._pCard == null)
                {
                    return -1;
                }

                if (moveGroup._nAxisArr == null || moveGroup._nAxisArr.Length <= 1)
                {
                    return -1;
                }
                if (moveGroup._pGroup == null)
                {
                    return -1;
                }

                return moveGroup._pCard.GetGpLeftSpace(moveGroup._pGroup);

            }
            return -1;
        }
        public int GpRunAlready(string strGpName)
        {
            if (m_dicGroup.ContainsKey(strGpName))
            {
                MoveGroup moveGroup = m_dicGroup[strGpName];
                if (moveGroup._pCard == null)
                {
                    return 0;
                }

                if (moveGroup._nAxisArr == null || moveGroup._nAxisArr.Length <= 1)
                {
                    return 0;
                }
                if (moveGroup._pGroup == null)
                {
                    return 0;
                }

                return moveGroup._pCard.GpRunAlready(moveGroup._pGroup);

            }
            return 0;
        }
        public bool RestGpErr(string strGpName)
        {
            if (m_dicGroup.ContainsKey(strGpName))
            {
                MoveGroup moveGroup = m_dicGroup[strGpName];
                if (moveGroup._pCard == null)
                {
                    return false;
                }

                if (moveGroup._nAxisArr == null || moveGroup._nAxisArr.Length <= 1)
                {
                    return false;
                }
                if (moveGroup._pGroup == null)
                {
                    return false;
                }
                return moveGroup._pCard.ResetGpErr(moveGroup._pGroup);
            }
            return false;
        }
        public bool Line2Axisabs(string strGpName, double xAxisPos, double yAxisPos, ref string strError)
        {
            double[] posDst = new double[] { xAxisPos, yAxisPos };
            if (m_dicGroup.ContainsKey(strGpName))
            {
                MoveGroup moveGroup = m_dicGroup[strGpName];
                if (moveGroup._pCard == null)
                {
                    return false;
                }

                if (moveGroup._nAxisArr == null || moveGroup._nAxisArr.Length != 2)
                {
                    return false;
                }

                //轴运动安全检查
                bool bSave = true;
                if (m_eventIsSafeWhenAxisMove != null)
                {
                    Delegate[] delegates = m_eventIsSafeWhenAxisMove.GetInvocationList();
                    double currentpos = 0;
                    double destpos = 0;
                    foreach (var tem in delegates)
                    {
                        MethodInfo methodInfo = tem.GetMethodInfo();
                        for (int nAxisNo = 0; nAxisNo < 2; nAxisNo++)
                        {
                            destpos = posDst[nAxisNo];
                            currentpos = MotionMgr.GetInstace().GetAxisActPos(moveGroup._nSysAxisArr[nAxisNo]);
                            bSave = bSave & (bool)methodInfo.Invoke(null, new object[] { moveGroup._nSysAxisArr[nAxisNo], currentpos, destpos, MoveType.Line2AxisAbs });
                        }

                    }
                }
                if (!bSave)
                {
                    strError = $"{strGpName}群组Line2AxisAbs 安全检测失败";
                    DeviceDataCollect.GetInstance().Function_MachineLog(strGpName, strError);
                    return false;
                }
                DeviceDataCollect.GetInstance().Function_MachineLog(strGpName, $"{strGpName}群组Line2AxisAbs 运动开始");
                double ratex = moveGroup._pCard.GetAxisPulsesPerMM(moveGroup._nAxisArr[0]);
                double ratey = moveGroup._pCard.GetAxisPulsesPerMM(moveGroup._nAxisArr[1]);
                bool? brtn = moveGroup._pCard?.Line2Axisabs((IntPtr)moveGroup._pGroup, moveGroup._nAxisArr[0], moveGroup._nAxisArr[1],
                    xAxisPos * ratex, yAxisPos * ratey,
                    moveGroup._AccGp, moveGroup._DecGp,
                    moveGroup._VelHighGp, moveGroup._VelLowGp);
                if (brtn == null || brtn == false)
                    return false;
                return true;
            }
            else
            {
                strError = $"{strGpName}群组Line2AxisAbs 不存在";
                return false;
            }
        }

        public void CloseAxisToGroup(int[] nAxisArr, string GroupName)
        {
            if (m_dicGroup.ContainsKey(GroupName))
            {
                int[] _nAxisArr = new int[nAxisArr.Length];
                for (int i = 0; i < nAxisArr.Length; i++)
                {
                    _nAxisArr[i] = GetCardByIndexAxis(nAxisArr[i]).GetAxisNo(nAxisArr[i]);
                }
                MotionCardBase tempCardBase = m_dicGroup[GroupName]._pCard;
                object obj = (object)m_dicGroup[GroupName]._pGroup;
                tempCardBase.CloseAxisGroup(_nAxisArr, ref obj);
            }
        }
        ///群组 添加运动
        public bool AddBufMove(string GroupName, BufMotionType type, int mode, int nAxisNum, double velHigh, double velLow, double[] Point1, double[] Point2, int Circle = 1)
        {
            MoveGroup moveGroup = new MoveGroup();
            if (m_dicGroup.TryGetValue(GroupName, out moveGroup))
            {
                if (moveGroup._listBufMotionParams == null)
                    return false;
                if (type == BufMotionType.buf_IO || type == BufMotionType.buf_Delay || type == BufMotionType.buf_end)
                    return false;

                moveGroup._listBufMotionParams.Add(new BufMotionParam
                {
                    _Type = type,
                    _mode = mode,
                    _nAxisNum = nAxisNum,
                    _VelHigh = velHigh,
                    _VelLow = velLow,
                    _point1 = Point1,
                    _point2 = Point2,
                    _Circle = Circle
                });
                return true;
            }
            else
                return false;
        }
        ///群组 添加IO
        public bool AddBufIo(string GroupName, string IoName, bool bIoState)
        {

            MoveGroup moveGroup = new MoveGroup();
            if (m_dicGroup.TryGetValue(GroupName, out moveGroup))
            {
                if (moveGroup._listBufMotionParams == null)
                    return false;
                if (!IOMgr.GetInstace().GetOutputDic().ContainsKey(IoName))
                    return false;
                int nNum = moveGroup._nAxisArr == null ? 0 : moveGroup._nAxisArr.Length;
                moveGroup._listBufMotionParams.Add(new BufMotionParam
                {
                    _Type = BufMotionType.buf_IO,
                    _nAxisNo = IOMgr.GetInstace().GetOutputDic()[IoName]._AxisIndex,
                    _nCardNo = IOMgr.GetInstace().GetOutputDic()[IoName]._CardIndex,
                    _nIoNo = IOMgr.GetInstace().GetOutputDic()[IoName]._IoIndex,
                    _strIoName = IoName,
                    _nAxisNum = nNum,
                    _IoVal = bIoState,
                });
                return true;
            }
            else
                return false;
        }
        ///群组 添加Delay
        public bool AddBufDelay(string GroupName, int Time)
        {
            MoveGroup moveGroup = new MoveGroup();
            if (m_dicGroup.TryGetValue(GroupName, out moveGroup))
            {
                if (moveGroup._listBufMotionParams == null)
                    return false;
                moveGroup._listBufMotionParams.Add(new BufMotionParam
                {
                    _Type = BufMotionType.buf_Delay,
                    _nDelayMs = Time,
                });
                return true;
            }
            else
                return false;
        }
        public bool AddBufEnd(string GroupName)
        {
            MoveGroup moveGroup = new MoveGroup();
            if (m_dicGroup.TryGetValue(GroupName, out moveGroup))
            {
                if (moveGroup._listBufMotionParams == null)
                    return false;
                int nNum = moveGroup._nAxisArr == null ? 0 : moveGroup._nAxisArr.Length;
                moveGroup._listBufMotionParams.Add(new BufMotionParam
                {
                    _Type = BufMotionType.buf_end,
                    _nAxisNum = nNum,
                });
                return true;
            }
            else
                return false;
        }
        public bool ClearBufMove(string strGroupName)
        {
            MoveGroup moveGroup = new MoveGroup();
            if (m_dicGroup.TryGetValue(strGroupName, out moveGroup))
            {
                moveGroup._listBufMotionParams.Clear();
                return moveGroup._pCard.ClearBufMove(moveGroup._pGroup);
            }
            return false;
        }
        public bool BufTrans(string strGroupName, ref string strError)
        {
            bool bRtn = true;
            MoveGroup moveGroup = new MoveGroup();
            if (m_dicGroup.TryGetValue(strGroupName, out moveGroup))
            {
                if (moveGroup._listBufMotionParams == null)
                    return false;
                ushort[] shortData = new ushort[moveGroup._nAxisArr.Length];
                for (int i = 0; i < moveGroup._nAxisArr.Length; i++)
                {
                    shortData[i] = (ushort)moveGroup._nAxisArr[i];
                }
                string str_TranInfo = "";
                foreach (var tem in moveGroup._listBufMotionParams)
                {
                    double[] point1Pulse = null;
                    double[] point2Pulse = null;
                    switch (tem._Type)
                    {
                        #region buf_IO
                        case BufMotionType.buf_IO:
                            for (int i = 0; i < moveGroup._nAxisArr.Length; i++)
                            {
                                if (moveGroup._nAxisArr[i] == tem._nAxisNo)
                                {
                                    break;
                                }
                            }
                            bRtn = bRtn & moveGroup._pCard.AddBufIo(moveGroup._pGroup, tem._strIoName, tem._IoVal, ref strError);
                            str_TranInfo += $"Buf={strGroupName} 添加IO控制 IO名称={tem._strIoName},值={tem._IoVal}  结果={strError}\n";
                            break;

                        #endregion

                        #region buf_Delay
                        case BufMotionType.buf_Delay:
                            bRtn = bRtn & moveGroup._pCard.AddBufDelay(moveGroup._pGroup, tem._nDelayMs, ref strError);
                            str_TranInfo += $"Buf={strGroupName} 添加延时控制 时长={tem._nDelayMs}  结果={strError}\n";
                            break;
                        #endregion

                        #region buf_Arc2dAbsAngleCCW
                        case BufMotionType.buf_Arc2dAbsAngleCCW:
                        case BufMotionType.buf_Arc2dAbsAngleCW:
                            double acc1 = 0;
                            if (tem._point1 != null)
                            {
                                point1Pulse = new double[tem._point1.Length];
                                point2Pulse = new double[tem._point1.Length];//不做转换
                                for (int i = 0; i < tem._point1.Length; i++)
                                {
                                    point1Pulse[i] = GetAxisPulsesPerMM(moveGroup._nSysAxisArr[i]) * tem._point1[i];
                                    point2Pulse[i] = GetAxisPulsesPerMM(moveGroup._nSysAxisArr[i]) * tem._point2[i];
                                    acc1 = GetAxisPulsesPerMM(moveGroup._nSysAxisArr[i]) * GetAxisSpeed(moveGroup._nSysAxisArr[i], tem._VelHigh);
                                }

                            }
                            bRtn = bRtn & moveGroup._pCard.AddBufMove(moveGroup._pGroup, tem._Type, tem._mode, shortData, acc1, acc1, point1Pulse, point2Pulse, tem._Circle, ref strError);
                            str_TranInfo += $"Buf={strGroupName} 添加圆弧运动 X1={point1Pulse[0]},Y1={point1Pulse[1]},X2={point2Pulse[0]},Y2={point2Pulse[1]},圈数={tem._Circle} 结果={strError}\n";
                            break;
                        #endregion
                        default:
                            point1Pulse = null;
                            point2Pulse = null;
                            double acc3 = 0;
                            if (tem._point1 != null)
                            {
                                point1Pulse = new double[tem._point1.Length];
                                for (int i = 0; i < tem._point1.Length; i++)
                                {
                                    point1Pulse[i] = GetAxisPulsesPerMM(moveGroup._nSysAxisArr[i]) * tem._point1[i];
                                    acc3 = GetAxisPulsesPerMM(moveGroup._nSysAxisArr[i]) * GetAxisSpeed(moveGroup._nSysAxisArr[i], tem._VelHigh);
                                }

                            }
                            if (tem._point2 != null)
                            {
                                point2Pulse = new double[tem._point2.Length];
                                for (int i = 0; i < tem._point2.Length; i++)
                                {
                                    point2Pulse[i] = GetAxisPulsesPerMM(moveGroup._nSysAxisArr[i]) * tem._point2[i];
                                }

                            }
                            bRtn = bRtn & moveGroup._pCard.AddBufMove(moveGroup._pGroup, tem._Type, tem._mode,
                                shortData, acc3, acc3,
                                point1Pulse, point2Pulse, tem._Circle, ref strError);
                            str_TranInfo += $"Buf={strGroupName} 添加直线运动 X1={point1Pulse[0]},Y1={point1Pulse[1]},X2={point2Pulse[0]},Y2={point2Pulse[1]} 结果={strError}\n";
                            break;
                    }

                }
                DeviceDataCollect.GetInstance().Function_MachineLog(strGroupName, strError);
                return bRtn;
            }
            else
                return false;


        }
        public bool BufStart(string strGroupName)
        {
            MoveGroup moveGroup = new MoveGroup();
            if (m_dicGroup.TryGetValue(strGroupName, out moveGroup))
            {
                DeviceDataCollect.GetInstance().Function_MachineLog(strGroupName, $"开始执行Buf群组={strGroupName}");
                return moveGroup._pCard.StartBufMove(moveGroup._pGroup);
            }
            return false;

        }
        public bool SetBufMoveParam(string strGroupName, double velhigh, double vellow, double acc, double dec, ref string strError)
        {
            MoveGroup moveGroup = new MoveGroup();
            if (m_dicGroup.TryGetValue(strGroupName, out moveGroup))
            {
                ushort[] shortData = new ushort[moveGroup._nAxisArr.Length];
                for (int i = 0; i < moveGroup._nAxisArr.Length; i++)
                {
                    shortData[i] = (ushort)moveGroup._nAxisArr[i];
                }
                return moveGroup._pCard.SetBufMoveParam(moveGroup._pGroup, shortData, velhigh, vellow, acc, dec, ref strError);
            }
            return false;

        }

        public bool ReadSDOData(int nAxis, short nSlave, ushort Index, byte nSubIndex = 0, uint nUnitNum = 16)
        {
            MotionCardBase tempCardBase = GetCardByIndexAxis(nAxis);
            if (tempCardBase != null)
            {
                nAxis = tempCardBase.GetAxisNo(nAxis);
                return tempCardBase.ReadSDOData(nAxis, nSlave, Index, nSubIndex, nUnitNum);
            }
            else
                return false;
        }

        public bool WriteSDOData(int nAxis, short nSlave, int val, ushort Index, byte nSubIndex = 0, uint nUnitNum = 16)
        {
            MotionCardBase tempCardBase = GetCardByIndexAxis(nAxis);
            if (tempCardBase != null)
            {
                nAxis = tempCardBase.GetAxisNo(nAxis);
                return tempCardBase.WriteSDOData(nAxis, nSlave, val, Index, nSubIndex, nUnitNum);
            }
            else
                return false;
        }
        public string GetAxisErrorString(int nAxis)
        {
            MotionCardBase tempCardBase = GetCardByIndexAxis(nAxis);
            if (tempCardBase != null)
            {
                nAxis = tempCardBase.GetAxisNo(nAxis);
                return tempCardBase.GetAxisErrorString(nAxis);
            }
            else
                return "";
        }

    }

}
